{
 "cells": [
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-15T06:57:10.062458Z",
     "start_time": "2025-05-15T06:57:10.059350Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import numpy as np\n",
    "from scipy.stats import multivariate_normal"
   ],
   "id": "4bcd4201de230737",
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-15T06:57:10.084858Z",
     "start_time": "2025-05-15T06:57:10.078942Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class GMM:\n",
    "    def __init__(self, n_components, max_iter=100, tol=1e-4):\n",
    "        self.n_components = n_components\n",
    "        self.max_iter = max_iter\n",
    "        self.tol = tol\n",
    "        self.weights = None\n",
    "        self.means = None\n",
    "        self.covariances = None\n",
    "        self.converged = False\n",
    "\n",
    "    def _initialize_parameters(self, X):\n",
    "        n_samples, n_features = X.shape\n",
    "        self.weights = np.ones(self.n_components) / self.n_components\n",
    "        random_idx = np.random.choice(n_samples, self.n_components, replace=False)\n",
    "        self.means = X[random_idx]\n",
    "        self.covariances = [np.eye(n_features) for _ in range(self.n_components)]\n",
    "\n",
    "    def _e_step(self, X):\n",
    "        n_samples = X.shape[0]\n",
    "        responsibilities = np.zeros((n_samples, self.n_components))\n",
    "\n",
    "        for i in range(self.n_components):\n",
    "            responsibilities[:, i] = self.weights[i] * multivariate_normal.pdf(X, mean=self.means[i], cov=self.covariances[i])\n",
    "\n",
    "        responsibilities /= responsibilities.sum(axis=1, keepdims=True)\n",
    "        return responsibilities\n",
    "\n",
    "    def _m_step(self, X, responsibilities):\n",
    "        n_samples, n_features = X.shape\n",
    "        for i in range(self.n_components):\n",
    "            weight = responsibilities[:, i].sum()\n",
    "            mean = (X * responsibilities[:, i].reshape(-1, 1)).sum(axis=0) / weight\n",
    "            covariance = np.dot((responsibilities[:, i].reshape(-1, 1) * (X - mean)).T, (X - mean)) / weight\n",
    "\n",
    "            self.weights[i] = weight / n_samples\n",
    "            self.means[i] = mean\n",
    "            self.covariances[i] = covariance\n",
    "\n",
    "    def fit(self, X):\n",
    "        self._initialize_parameters(X)\n",
    "\n",
    "        for iteration in range(self.max_iter):\n",
    "            old_means = self.means.copy()\n",
    "\n",
    "            responsibilities = self._e_step(X)\n",
    "            self._m_step(X, responsibilities)\n",
    "\n",
    "            if np.max(np.abs(self.means - old_means)) < self.tol:\n",
    "                self.converged = True\n",
    "                break\n",
    "\n",
    "    def predict(self, X):\n",
    "        responsibilities = self._e_step(X)\n",
    "        return np.argmax(responsibilities, axis=1)\n"
   ],
   "id": "d89151e0688edf2",
   "outputs": [],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-15T06:57:10.163404Z",
     "start_time": "2025-05-15T06:57:10.092868Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 生成一些模拟数据\n",
    "np.random.seed(42)\n",
    "n_samples = 300\n",
    "n_features = 2\n",
    "n_components = 3\n",
    "\n",
    "true_means = np.array([[0, 0], [3, 3], [6, 0]])\n",
    "true_covariances = [np.eye(n_features) for _ in range(n_components)]\n",
    "true_weights = np.array([0.4, 0.3, 0.3])\n",
    "\n",
    "X = np.concatenate([\n",
    "    np.random.multivariate_normal(true_means[i], true_covariances[i], int(n_samples * true_weights[i]))\n",
    "    for i in range(n_components)\n",
    "])\n",
    "\n",
    "# 初始化并训练GMM模型\n",
    "gmm = GMM(n_components=n_components)\n",
    "gmm.fit(X)\n",
    "\n",
    "# 预测聚类标签\n",
    "labels = gmm.predict(X)\n",
    "\n",
    "print(\"预测的聚类标签:\", labels)\n"
   ],
   "id": "61bb6073bb5e481f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测的聚类标签: [0 0 0 0 0 1 1 1 0 1 0 1 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0\n",
      " 1 0 1 0 0 1 0 0 0 1 1 0 0 1 1 0 0 0 1 0 0 1 0 1 1 0 1 1 1 0 0 1 1 0 1 0 1\n",
      " 0 0 0 1 0 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 2 0 0 0 1 0 1\n",
      " 1 0 1 0 0 1 0 1 0 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2]\n"
     ]
    }
   ],
   "execution_count": 5
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
